/*
 * File Name: BaseAsyncTask.java
 * 
 * Copyright (c) 2011, FIL Limited. 
 * All Rights Reserved.
 * This software is the confidential and proprietary information of FIL Limited.
 *
 */
package com.idrem.asynctask;

import android.os.AsyncTask;

/**
 * Base AsyncTask which extends Android AsyncTask
 */
public abstract class BaseAsyncTask<Params, Progress, Result>
    extends AsyncTask<Params, Progress, Result>
{
    private TaskOnPreExecuteListener mtaskOnPreExecuteListener;

    private TaskOnProgressUpdateListener<Progress> mtaskOnProgressUpdateListener;

    private TaskOnPostExecuteListener<? super Result> mtaskOnPostExecuteListener;

    private TaskOnCancelledListener mtaskOnCancelledListener;

    /**
     * bind pre execution event listener to the task
     * 
     * @param taskOnPreExecuteListener
     */
    public void setTaskOnPreExecuteListener(TaskOnPreExecuteListener taskOnPreExecuteListener)
    {
        this.mtaskOnPreExecuteListener = taskOnPreExecuteListener;
    }

    /**
     * bind progress update event listener to the task
     * 
     * @param taskOnProgressUpdateListener
     */
    public void setTaskOnProgressUpdateListener(TaskOnProgressUpdateListener<Progress> taskOnProgressUpdateListener)
    {
        this.mtaskOnProgressUpdateListener = taskOnProgressUpdateListener;
    }

    /**
     * bind onpost execution event listener to the task
     * 
     * @param taskOnPostExecuteListener
     */
    public void setTaskOnPostExecuteListener(TaskOnPostExecuteListener<? super Result> taskOnPostExecuteListener)
    {
        this.mtaskOnPostExecuteListener = taskOnPostExecuteListener;
    }

    /**
     * bind cancel event listener to the task
     * 
     * @param taskOnCancelledListener
     */
    public void setTaskOnCancelledListener(TaskOnCancelledListener taskOnCancelledListener)
    {
        this.mtaskOnCancelledListener = taskOnCancelledListener;
    }

    /**
     * 
     * @see android.os.AsyncTask#onPreExecute()
     */
    @Override
    protected void onPreExecute()
    {
        if (mtaskOnPreExecuteListener != null)
        {
            mtaskOnPreExecuteListener.onPreExecute();
        }
    }

    /**
     * 
     * @see android.os.AsyncTask#onProgressUpdate(Progress[])
     */
    @Override
    protected void onProgressUpdate(Progress... values)
    {
        if (mtaskOnProgressUpdateListener != null)
        {
            mtaskOnProgressUpdateListener.onProgressUpdate(values);
        }
    }

    /**
     * 
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(Result result)
    {
        if (mtaskOnPostExecuteListener != null)
        {
            mtaskOnPostExecuteListener.onPostExecute(new TaskResult<Result>(this, result, STATUS_SUCCESS));
        }
    }

    /**
     * 
     * @see android.os.AsyncTask#onCancelled()
     */
    @Override
    protected void onCancelled()
    {
        if (mtaskOnCancelledListener != null)
        {
            mtaskOnCancelledListener.onCancelled();
        }
    }

    /**
     * Interface used to allow the creator to run some code before the task
     * starts
     * 
     */
    public static interface TaskOnPreExecuteListener
    {
        /**
         * Runs on the UI thread. this method will be invoked before the task
         * starts
         */
        public void onPreExecute();
    }

    /**
     * Interface used to allow the creator to run some code to update progress
     * 
     * @param <Progress> The values indicating progress.
     */
    public static interface TaskOnProgressUpdateListener<Progress>
    {
        /**
         * Runs on the UI thread. this method will be invoked after
         * {@link #publishProgress} is invoked.
         * 
         * @param values The values indicating progress.
         */
        public void onProgressUpdate(Progress... values);
    }

    /**
     * Interface used to allow the creator to run some code when the task has
     * been finished
     * 
     * @param <T>
     */
    public static interface TaskOnPostExecuteListener<T>
    {
        /**
         * Runs on the UI thread. this method will be invoked when the task has
         * been finished
         * 
         * @param result computed result of the task
         */
        public void onPostExecute(final TaskResult<? extends T> result);
    }

    /**
     * Interface used to allow the creator to run some code when the task has
     * been canceled
     */
    public static interface TaskOnCancelledListener
    {
        /**
         * Runs on the UI thread. this method will be invoked when the task has
         * been canceled
         */
        public void onCancelled();
    }

    // Indicates that the task has been executed successfully
    public static final int STATUS_SUCCESS = 0;

    // Indicates that the task has been canceled
    public static final int STATUS_CANCEL = 1;

    // Indicates that the task has been executed fail
    public static final int STATUS_FAIL = 2;

    /**
     * A class contains a task output.
     * 
     */
    public static class TaskResult<Result>
    {
        /**
         * The output of a task, can be null.
         */
        public final Result Value;

        /**
         * A task produces this result.
         */
        public final BaseAsyncTask<?, ?, Result> Task;

        /**
         * The final status of running a task.
         */
        public final int Status;

        /**
         * Constructor.
         */
        TaskResult( BaseAsyncTask<?, ?, Result> task, Result value, int status )
        {
            this.Value = value;
            this.Task = task;
            this.Status = status;
        }
    }
}
